package com.protocols.sctp.m3ua;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.Arrays;

import com.protocols.*;
import com.protocols.sctp.m3ua.sccp.SccpUnitDataMsg;

public class ProtocolData implements Serializable{
	private OctaveInteger ParameterTag= new OctaveInteger(528,2);// Protocol Data 
	private OctaveInteger ParameterLength= new OctaveInteger(2);
	private OctaveInteger OPC= new OctaveInteger(4);
	private OctaveInteger DPC= new OctaveInteger(4);
	private OctaveInteger ServiceIndicator= new OctaveInteger(1);
	private OctaveInteger NI= new OctaveInteger(1);
	private OctaveInteger MP= new OctaveInteger(1);
	private OctaveInteger SLS= new OctaveInteger(1);
	private Boolean Visible=false;
	public GeneralProtocolData Payload = new DummyPayload();
	
	public ProtocolData() {
		
	}
	
	public ProtocolData(int OPC, int DPC, int SI,int NI, int MP, int SLS) {
		this.OPC.Value=OPC;
		this.DPC.Value=DPC;
		this.ServiceIndicator.Value=SI;
		this.NI.Value=NI;
		this.MP.Value=MP;
		this.SLS.Value=SLS;
		Visible=true;
		
	}

	public void setProtocolDataParameters(int OPC, int DPC, int SI,int NI, int MP, int SLS) {
		this.OPC.Value=OPC;
		this.DPC.Value=DPC;
		this.ServiceIndicator.Value=SI;
		this.NI.Value=NI;
		this.MP.Value=MP;
		this.SLS.Value=SLS;
		Visible=true;
	}

	public void toggleDestination(){
		int pointcode = OPC.getValue();
		OPC.setValue(DPC.getValue());
		DPC.setValue(pointcode);
	}

	public int getOPC() {
		return OPC.Value;
	}

	public void setOPC(int oPC) {
		Visible=true;
		OPC.Value = oPC;
	}

	public int getDPC() {
		return DPC.Value;
	}

	public void setDPC(int dPC) {
		Visible=true;
		DPC.Value = dPC;
	}

	public int getServiceIndicator() {
		return ServiceIndicator.Value;
	}

	public void setServiceIndicator(int SI) {
		Visible=true;
		ServiceIndicator.Value = SI;
	}

	public int getNI() {
		return NI.Value;
	}

	public void setNI(int nI) {
		Visible=true;
		NI.Value = nI;
	}

	public int getMP() {
		return MP.Value;
	}

	public void setMP(int mP) {
		Visible=true;
		MP.Value = mP;
	}

	public int getSLS() {
		return SLS.Value;
	}

	public void setSLS(int sLS) {
		Visible=true;
		SLS.Value = sLS;
	}

	public int getLength() {
		return getByteArray().length;
	}


	public byte [] getByteArray(){		
		if(Payload==null){
			return  new byte[0];
		}
		else
		{
			byte [] payload = Payload.getByteArray();
			ParameterLength.setValue(16+payload.length);
			int len=payload.length;
			byte [] padding;
			if (len%4==0)
				padding= new byte[0];
			else if (len%4==1)
				padding= new byte[3];
			else if (len%4==2)
				padding= new byte[2];
			else 
				padding= new byte[1];
			
			return  !Visible?new byte[0]:ProtoOperations.concatArrays(ParameterTag.getByteArray(), ParameterLength.getByteArray(), OPC.getByteArray(), DPC.getByteArray(),ServiceIndicator.getByteArray(),NI.getByteArray(),MP.getByteArray(),SLS.getByteArray(),Payload.getByteArray(),padding);
		}

	}

	public GeneralProtocolData getPayload() {
		return Payload;
	}

	public void setPayload(GeneralProtocolData payload) {
		Payload = payload;
	}
	
	public byte [] decode(byte [] input) throws ProtocolStackException{
		
		if (input.length==0)
			return new byte[0];
		else if (input.length<8 && input.length>0)
			throw new ProtocolStackException("Decode Failure:M3UAProtocolData"+ProtoOperations.getHexString(input));
		
		
		if (input[0]==2 && input[1]==0x10)
		{			
			ParameterLength.Value=ProtoOperations.intFromByteArray(input, 2, 2);
			byte [] payloadinput = ProtoOperations.extractByteArray(input, 0, ParameterLength.Value);
			setOPC( ProtoOperations.intFromByteArray(payloadinput, 4,  4));
			setDPC( ProtoOperations.intFromByteArray(payloadinput, 8,  4));
			setServiceIndicator( ProtoOperations.intFromByteArray(payloadinput, 12,  1));
			setNI( ProtoOperations.intFromByteArray(payloadinput, 13,  1));
			setSLS( ProtoOperations.intFromByteArray(payloadinput, 14,  1));
			
			int len=ParameterLength.Value;	// Removing the padding
			int padding=0;
			if (len%4==0)
				padding= 0;
			else if (len%4==1)
				padding= 3;
			else if (len%4==2)
				padding= 2;
			else 
				padding= 1;
			
			byte [] payload=ProtoOperations.extractByteArray(payloadinput, 16, payloadinput.length-16);
			byte[] Correlation=new byte[0];
			if (ParameterLength.Value+padding+1<=input.length)
				Correlation= ProtoOperations.extractByteArray(input, ParameterLength.Value+padding+1, input.length-(ParameterLength.Value+padding));
			return ProtoOperations.concatArrays(new byte[]{(byte)payload.length}, payload,Correlation);
				
		}
		else
			throw new ProtocolStackException("Decode Failure:M3UAProtocolData"+ProtoOperations.getHexString(input));

				
	}
}
